if (Best==undefined){
	var Best={};
}
//global var
Best.indexOfEntries = [];
//global var end

Best.Tree = Class.create();

Best.Tree.prototype = {
	initialize: function(options){
		this.options = {
			name: "tree",  //tree name
			target: "_self", //node link target
			url: null, //node link url
			getChildrenDataUrl: "",  //获取子节点的url（ajax tree）
			createActionUrl: "", //创建新节点的action url
			updateActionUrl: "", //修改节点的action url
			deleteActionUrl: "", //删除节点的action url
			changeParentActionUrl: "", //拖动改变父节点的action url
			searchActionUrl: "", //搜索的action url
			computeCheckedNodeKeysActionUrl:"", //计算选中的节点的key列表的action url
			isShowCheckbox: false, //是否显示checkbox
			isShowToolbar: true, //是否显示toolbar
			isRecursive: true, //选中checkbox的时候，是否父子递归联动
			scrollContainerId: '', //scroll container element id
			root: {}, //tree root node
			checkedNodeKeys: [], //选中的节点的key的列表
			onnodeclick: null, //node click callback function
			onnodedblclick: null, //node double click callback function
			oncheckboxclick: null, //node checkbox click callback function
			afterChangeParent: null, //node parent change callback function
			afterAddFolder: Prototype.emptyFunction, //添加文件夹回调函数
			afterAddFile: Prototype.emptyFunction, //添加文件回调函数
			afterEdit: Prototype.emptyFunction, //修改完成回调函数
			afterDelete: Prototype.emptyFunction //删除完成回调函数
	    }
	    Object.extend(this.options, options || {});
 		TreeUtil.USEICONS = true;
 		TreeUtil.HIGHLIGHT = true;
 		//TreeUtil.STARTALLOPEN = true;
 		this.root = this.options.root; //根节点
 		this.isAjaxTree = (this.options.getChildrenDataUrl != ""); //是否为ajax tree
 		
 		this.options.treeInstance = this;
 		
 		//original global var
	    this.foldersTree;
	    this.lastClicked = null;
		this.lastClickedColor;
		this.lastClickedBgColor;
		
		this.nEntries = 0;
		this.browserVersion = 0; 
		this.selectedFolder = 0;
		this.lastOpenedFolder = null;
		//original global var end
		
	    this._create();
	},
	/**
	 * 展开所有节点
	 */
	expandAll: function(){
		TreeUtil.renderAllTree(this.foldersTree, null);
	},
	/**
	 * 收起所有节点
	 */
	unexpandAll: function(){
		TreeUtil.hideWholeTree(this.foldersTree, false);
	},
	_create: function(){
		var root = this.options.root;
		if(root != null && root.length <= 0){
			return;
		}
		this._showNode(root, null);
  		TreeUtil.initializeDocument(this.foldersTree);
	},
	_showNode: function(node, parentNodeElement, isStatic, renderDecorator){
		if(isStatic == undefined){
			isStatic = false;
		}
		if(renderDecorator == undefined){
			renderDecorator = Prototype.emptyFunction;
		}
		if(node != null){
			this.options.renderDecorator = renderDecorator;
			
			node.options = this.options;
			node.isStatic = isStatic;
			if(node.options.checkedNodeKeys.indexOf(node.key) != -1){
				node.checkboxState = 1;
			}else if(node.options.checkedNodeKeys.indexOf("^_^" + node.key) != -1){
				node.checkboxState = 3;
			}
			if(node.isLeaf && parentNodeElement != null){
				var url = TreeUtil.getLinkUrl(node, this.options.url);
				
				TreeUtil.insDoc(parentNodeElement, TreeUtil.gLnk(this.options.target, node.value, url, this.options.name, node));
				parentNodeElement.isChildrenDataInitialized = true;
			}else{
				if(parentNodeElement == null){
					var nodeDoc = this.foldersTree = parentNodeElement = TreeUtil.gFld("<b>" + node.value + "</b>", "javascript:undefined", this.options.name, node);
				}else{
					var nodeDoc = parentNodeElement = TreeUtil.insFld(parentNodeElement, TreeUtil.gFld(node.value, "javascript:undefined", this.options.name, node));
				}
				
				var children = node.children;
	  			var child;
	  			for(var i=0; i<children.length; i++){
	  				child = children[i];
	  				this._showNode(child, parentNodeElement, isStatic, renderDecorator);
	  			}
	  			if(children.length > 0){
	  				parentNodeElement.isChildrenDataInitialized = true;
	  			}else{
		  			if(!this.isAjaxTree || isStatic){
		  				parentNodeElement.isChildrenDataInitialized = true;
		  			}
	  			}
			}
		}
	},
	/**
	 * 根据keyword搜索树节点，并把搜到的匹配节点展示出来(本地js搜索)
	 */
	search: function(keyword){
		this.unexpandAll();
		if(!this.isSearching){
			this.isSearching = true;
			TreeUtil.widthFirstTraverse(this.foldersTree, true, this.highlightNodeKeyword.bind(this, keyword), function(){this.isSearching=false}.bind(this));
		}
	},
	highlightNodeKeyword: function(keyword, nodeObj){
		var descContenDiv = $('descContent' + nodeObj.id);
		if(descContenDiv){
			var html = descContenDiv.innerHTML.replace("<b>", "");
			html = html.replace("<B>", "");
			html = html.replace("</b>", "");
			html = html.replace("</B>", "");
			descContenDiv.innerHTML = html;
		}
		if(nodeObj.data.value.indexOf(keyword) != -1){
			this.expandNode(nodeObj);
			var descContenDiv = $('descContent' + nodeObj.id);
			if(descContenDiv != undefined){
				descContenDiv.innerHTML = descContenDiv.innerHTML.replace(keyword, keyword.bold());
			}
		}
		return true;
	},
	/**
	 * 根据keyword搜索树节点，并把搜到的匹配节点展示出来(搜索在服务器上进行，然后在用js显示结果)
	 */
	searchOnServer: function(keyword){
		if(Utils.RTrim(keyword) != ""){ //不为空的时候显示搜索树
			if(!this.isSearching){
				this.isSearching = true;
				jQuery.post(
					this.foldersTree.data.options.searchActionUrl,
					{"keyword":keyword},
					function(dataFromServer){
						dataFromServer = eval("(" + dataFromServer + ")");
						this.removeWholeTree();
						this._showNode(dataFromServer[4].tree, null, true, this.highlightNodeKeyword.bind(this, keyword));
	  					TreeUtil.initializeDocument(this.foldersTree);
	  					this.expandAll();
	  					this.isSearching = false;
					}.bind(this)
				)
				this.isShowingSearchResult = true;
			}
		}else{//为空的时候显示原来的树
			this.removeWholeTree();
			this._create();
			this.isShowingSearchResult = false;
		}
	},
	/**
	 * 展开节点nodeObj所有祖先节点
	 * @param nodeObj
	 * 			要展开的节点对象
	 */
	expandNode: function(nodeObj){
		var parentObj = nodeObj.parentObj;
		var stack = [];
		
		while(parentObj != undefined){
			if(!parentObj.isOpen){
				stack.push(parentObj);
			}
			parentObj = parentObj.parentObj;
		}
		var node = stack.pop();
		while(node != null){
			if(!node.isRendered){
				node.renderOb(node.parentObj.navObj);
			}
			node.setState(true);
			node = stack.pop();
		}
	},
	/**
	 * 获取所有选中的节点的key list（灰选的节点在key前面加上"^_^"前缀
	 */
	getAllCheckedNodeKeys: function(){
		var result = this.foldersTree.data.options.checkedNodeKeys;
		return result;
	},
	/**
	 * 找到所有checkbox被选中的节点，如果一个节点的所有子孙节点都被选中，则只返回该节点，否则返回所有被选中的
	 * 子孙节点
	 * @param afterFindCB
	 * 			计算结果通知的回调函数。参数为所有被选中的节点对象数组
	 * @return
	 * 			返回所有被选中的节点对象数组
	 */
	findAllCheckedNode: function(afterFindCB){
		if(afterFindCB == undefined){
			afterFindCB = Prototype.emptyFunction;
		}
		var result = [];
		
		var visitor;
		if(this.isShowingSearchResult){
			var checkedNodeKeys = this.foldersTree.data.options.checkedNodeKeys;
			this._computeCheckedNodeKeys(checkedNodeKeys, 
					function(){
						visitor = this.findAllCheckedNodeVisitor.bind(this, result);
						this.renderAllInitializedTreeNode();
						TreeUtil.widthFirstTraverse(this.foldersTree, false, visitor);
						afterFindCB(result);
					}.bind(this)
				);
		}else{
			this.renderAllInitializedTreeNode();
			visitor = this.findAllCheckedNodeVisitor.bind(this, result);
			TreeUtil.widthFirstTraverse(this.foldersTree, false, visitor);
			afterFindCB(result);
		}
	},
	findAllCheckedNodeVisitor: function(checkedNodeList, nodeObj){
		if(nodeObj.checkbox && nodeObj.checkbox.checked && nodeObj.checkbox.disabled == false){
			checkedNodeList.push(nodeObj);
			if(this.options.isRecursive){
				return false;
			}
		}
		return true;
	},
	/**
	 * 当正在显示搜索结果时查找所有被选中的节点的visitor函数
	 */
	findAllCheckedNodeVisitorWhenSearching: function(checkedNodeList, nodeObj){
		if(nodeObj.checkbox && nodeObj.checkbox.checked && nodeObj.checkbox.disabled == false && nodeObj.nChildren == 0){
			checkedNodeList.push(nodeObj);
			return false;
		}
		return true;
	},
	/**
	 * 返回所有选中的节点列表
	 */
	getAllCheckedNode: function(){
		return this.foldersTree.data.options.checkedNodeKeys;
	},
	/**
	 * 显示所有checked的节点 
	 * @param checkNodeKeys
	 * 			checked的节点key列表
	 */
	showAllCheckedNode: function(checkedNodeKeys){
		if(checkedNodeKeys != undefined && checkedNodeKeys.indexOf('%') != -1){//全选
			try{
				checkedNodeKeys.clear();
				checkedNodeKeys.push(this.root.key);
				this.options.checkedNodeKeys = checkedNodeKeys;
	 			this.removeWholeTree();
	 			this._create();
			}catch(e){
				alert(e);
			}
		}else{
			this._computeCheckedNodeKeys(checkedNodeKeys);
		}
	},
	_computeCheckedNodeKeys: function(checkedNodeKeys, afterComputeCB){
		if(afterComputeCB == undefined){
			afterComputeCB = Prototype.emptyFunction;
		}
		if(checkedNodeKeys == undefined || checkedNodeKeys.length == 0){
			return;
		}
		var postData = [];
		postData = postData.concat(checkedNodeKeys);
		
		jQuery.post(
			this.foldersTree.data.options.computeCheckedNodeKeysActionUrl,
			{'checkedNodeKeys': postData, 'isRecursive':this.options.isRecursive},
			function(dataFromServer){
				var dataFromServer = eval("(" + dataFromServer + ")");
				if(dataFromServer[0] == "success"){
					checkedNodeKeys = dataFromServer[4].checkedNodeKeys;
					var treeWithCheckedNodeKeysRoot = dataFromServer[4].treeWithCheckedNodeKeysRoot;
					this.options.root = treeWithCheckedNodeKeysRoot;
					this.options.checkedNodeKeys = checkedNodeKeys;
					this.removeWholeTree();
					this._create();
					afterComputeCB();
				}else{
					Utils.showAjaxTip(dataFromServer);
				}
			}.bind(this)
		);
	},
	/**
	 * 把整棵树从dom中都删掉
	 */
	removeWholeTree: function(){
		var domRoot = $(this.options.name + "domRoot");
		if(domRoot){
			var childNodes = domRoot.childNodes;
			for(var i=0; i<childNodes.length; i++){
				this.removeNode(childNodes[i]);
				i--;
			}
		}
		/*
		var str = '';
		for(p in this.a){
			str += "'" + p + "',"; // + this.a[p] + '<br/>';
		}
		document.write(str);
		*/
	},
	removeNode: function(node){
		if(this.a == undefined){
			this.a = {};
		}
		var childNodes = node.childNodes;
		if(childNodes.length == 0){
			
		  	Utils.removeElementToRecoverMemory(node);
		  	
			node.parentNode.removeChild(node);
		}else{
			for(var i=0; i<childNodes.length; i++){
				this.removeNode(childNodes[i]);
				i--;
			}
		}
		
	},
	/**
	 * 把所有初始化好数据的节点的div都render出来
	 */
	renderAllInitializedTreeNode: function(){
		TreeUtil.traverseAllChild(
				this.foldersTree, 
				function(node){
					if(node.isChildrenDataInitialized){
						if(!node.isRendered){
							node.renderOb(node.parentObj.navObj);
						}
						if(!node.isOpen){
							node.setState(1);
							node.setState(0);
						}
					}
					return true;
				}, 
				false);
	},
	/**
	 * 对于有checkbox的ajax树，提交的时候需要对disabled的checkbox做一些特殊处理
	 * 	1. 需要把checkbox的disabled=true变为disabled=false
	 * 	2. 如果被disabled的checkbox对应的node展开过后被提交, 那么这个checkbox的value将被在前面加上"disabled_"前缀
	 * 	3. 如果被disabled的checkbox对应的node没有展开就被提交，那么这个checkbox的value将被在前面
	 * 	加上"disabled_uninitialized_"前缀
	 */
	markAjaxTreeCheckboxOnBeforeSubmit: function(){
		if(this.options.isShowCheckbox){
			TreeUtil.traverseAllChild(
					this.foldersTree, 
					function(node){
						if(node.checkbox != undefined && node.checkbox.disabled){
							node.checkbox.disabled = false;
							if(node.isChildrenDataInitialized){
								node.checkbox.value = 'disabled_' + node.checkbox.value;
							}else{
								node.checkbox.value = 'disabled_uninitialized_' + node.checkbox.value;
							}
						}
						return true;
					}, 
					false);
		}
	},
	/**
	 * depth first traverse
	 * @param visitor
	 * 			the visitor function to visit the tree node.
	 * 			this function's parameter is the tree node's nodeObj.
	 */
	traverseAllChild: function(visitor){
		if(visitor != undefined){
			TreeUtil.traverseAllChild(
						this.foldersTree, 
						visitor,
						false);
		}
	}
}